enchant();

window.onload = function() {
    var game = new Game(320, 320);
    game.preload(["charge.png", "chara1.gif"]);
    game.rootScene.backgroundColor = "#fff";

    game.onload = function() {
        var stage = new Group();
        game.rootScene.addChild(stage);

        var display = new Sprite(game.width, game.height);
        stage.addChild(display);
        display.image = new Surface(display.width, display.height);
        display.x = 0;
        display.y = 0;

        var ctx = display.image.context;

        var p1 = new Part(100, 100);
        p1.path = [
            { x:-30,y:-10 },
            { x: 30,y:-10 },
            { x: 30,y: 10 },
            { x:-30,y: 10 }
        ];

        // 右脚
        var right1 = new Part(20, 10);
        right1.fillStyle = "#333";
        right1.path = [
            { x:  0,y:  0 },
            { x:  2,y:  0 },
            { x:  2,y: 60 },
            { x:  0,y: 60 }
        ];
        p1.addChild(right1);
        var right2 = new Part(0, 60);
        right2.fillStyle = "#666";
        right2.path = [
            { x:  0,y:  0 },
            { x: 12,y:  0 },
            { x: 12,y: 60 }
        ];
        right1.addChild(right2);

        // 左脚
        var left1 = new Part(-20, 10);
        left1.fillStyle = "#333";
        left1.path = [
            { x:  0,y:  0 },
            { x:  2,y:  0 },
            { x:  2,y: 60 },
            { x:  0,y: 60 }
        ];
        p1.addChild(left1);
        var left2 = new Part(0, 60);
        left2.fillStyle = "#666";
        left2.path = [
            { x:  0,y:  0 },
            { x:-12,y:  0 },
            { x:-12,y: 60 }
        ];
        left1.addChild(left2);

        // 触手
        var parent = p1;
        var cells = [];
        for (var i = 0; i < 30; i++) {
            var cell = new Part(0, -10);
            cell.fillStyle = "#00f";
            cell.path = [
                { x:-5, y: 0 },
                { x: 0, y: 5 },
                { x: 5, y: 0 },
                { x: 0, y:-5 }
            ];
            parent.addChild(cell);
            parent = cell;
            cells.push(cell);
        }

        // キーフレーム
        // 1
        right1.setAngle(-30);
        right2.setAngle(30);
        left1.setAngle(30);
        left2.setAngle(-30);
        for (var i = 0; i < cells.length; i++) cells[i].setAngle(7);
        var kf1 = p1.pose();

        // 2
        right1.setAngle(-80);
        right2.setAngle(80);
        left1.setAngle(30);
        left2.setAngle(-30);
        for (var i = 0; i < cells.length; i++) cells[i].setAngle(0);
        var kf2 = p1.pose();

        // 3
        right1.setAngle(-60);
        right2.setAngle(60);
        left1.setAngle(60);
        left2.setAngle(-60);
        for (var i = 0; i < cells.length; i++) cells[i].setAngle(-7);
        var kf3 = p1.pose();

        // 4
        right1.setAngle(-30);
        right2.setAngle(30);
        left1.setAngle(80);
        left2.setAngle(-80);
        for (var i = 0; i < cells.length; i++) cells[i].setAngle(0);
        var kf4 = p1.pose();

	var keyFrames = [
	    kf1, kf2, kf3, kf4,
	    kf1, kf2, kf3, kf4,
	    kf1, kf2, kf3, kf4,
	    kf1, kf2, kf3, kf4,
	    kf1, kf4, kf3, kf2,
	    kf1, kf4, kf3, kf2,
	    kf1, kf4, kf3, kf2,
	    kf1, kf4, kf3, kf2
	];

        p1.pose(keyFrames[0]);

        p1.preBottom = p1.bottom();
        p1.addEventListener("enterframe", function() {
            var bottom = p1.bottom();

	    console.log(bottom.x - p1.preBottom.x);
            if (p1.preBottom.id == bottom.id) p1.x -= bottom.x - p1.preBottom.x;
            p1.preBottom = bottom;

            p1.y += 320 - bottom.y;
            this.draw(ctx);

            var all = 20;
            var cur = game.frame % all;
            var currentKeyFrame = Math.floor(game.frame / all) % keyFrames.length;

            p1.motion(keyFrames[currentKeyFrame], keyFrames[(currentKeyFrame+1)%keyFrames.length], cur, all);
        });
        stage.addChild(p1);

	var hex = new Part(10, 300);
	var r = Math.PI/3;
	var w = 30;
	hex.path = [
	    {x:Math.cos(r*0)*30,y:Math.sin(r*0)*30},
	    {x:Math.cos(r*1)*30,y:Math.sin(r*1)*30},
	    {x:Math.cos(r*2)*30,y:Math.sin(r*2)*30},
	    {x:Math.cos(r*3)*30,y:Math.sin(r*3)*30},
	    {x:Math.cos(r*4)*30,y:Math.sin(r*4)*30},
	    {x:Math.cos(r*5)*30,y:Math.sin(r*5)*30}
	];
	hex.preBottom = hex.bottom();
	hex.addEventListener("enterframe", function() {
	    this.rotate(2);

	    var b = this.bottom();
	    if (this.preBottom.id == b.id) this.x -= b.x - this.preBottom.x;
	    this.preBottom = b;
	    this.y += 320 - b.y;

	    this.draw(ctx);
	});
	stage.addChild(hex);
	
	hex.preBottom = hex.bottom();
        stage.addEventListener("enterframe", function() {
            display.image.clear();
        });
    };
    game.start();
};

/**
 * 多関節物体のパーツ.
 */
var PartId = {
    _id : 0,
    issue: function() {
        return this._id++;
    }
};
var Part = Class.create(Group, {
    initialize: function (x, y) {
        Group.call(this);
        this.path = [];
        this.fillStyle = "#000";
        this.x = x;
        this.y = y;
        this.angle = 0;
        this.id = PartId.issue();
    },
    draw: function(context, _x, _y) {
        if (!_x) _x = 0;
        if (!_y) _y = 0;
        if (this.path.length <= 1) return;
        context.fillStyle = this.fillStyle;
        context.beginPath();
        context.moveTo(this.x + this.path[0].x + _x, this.y + this.path[0].y + _y);
        for (var i = 1; i < this.path.length; i++) {
            context.lineTo(this.x + this.path[i].x + _x, this.y + this.path[i].y + _y);
        }
        context.closePath();
        context.fill();

        for (var i = 0; i < this.childNodes.length; i++) {
            this.childNodes[i].draw(context, this.x + _x, this.y + _y);
        }
    },
    rotate: function(angle) {
        this.angle = (this.angle + angle) % 360;
        this._application(Mtx33Rotate(angle));
    },
    setAngle: function(angle) {
        this.rotate(angle - this.angle);
    },
    _application: function(matrix) {
        for (var i = 0; i < this.path.length; i++) {
            this.path[i] = Vec2dTransformPoint(this.path[i].x, this.path[i].y, matrix);
        }
        for (var i = 0; i < this.childNodes.length; i++) {
            var newChildPos = Vec2dTransformPoint(this.childNodes[i].x, this.childNodes[i].y, matrix);
            this.childNodes[i].x = newChildPos.x;
            this.childNodes[i].y = newChildPos.y;
            this.childNodes[i]._application(matrix);
        }
    },
    pose: function() {
        if (arguments.length == 0) return this._getPose();
        else return this._setPose(arguments[0]);
    },
    _getPose: function() {
        var result = [];
        result.push(this.angle);
        for (var i = 0; i < this.childNodes.length; i++) {
            result.push(this.childNodes[i].pose());
        }
        return result;
    },
    _setPose: function(pose) {
        this.setAngle(pose[0]);
        for (var i = 0; i < this.childNodes.length; i++) {
            this.childNodes[i].pose(pose[1 + i]);
        }
    },
    motion: function(fromPose, toPose, cur, all) {
        this.setAngle(fromPose[0] + (toPose[0] - fromPose[0]) * cur/all);
        for (var i = 0; i < this.childNodes.length; i++) {
            this.childNodes[i].motion(fromPose[1 + i], toPose[1 + i], cur, all);
        }
    },
    bottom: function(bottom, _x, _y) {
        if (!bottom) bottom = {x:0,y:0,id:null};
        if (!_x) _x = 0;
        if (!_y) _y = 0;
        for (var i = 0; i < this.path.length; i++) {
            if (bottom.y < this.y + this.path[i].y + _y) {
                bottom.x = this.x + this.path[i].x + _x;
                bottom.y = this.y + this.path[i].y + _y;
                bottom.id = this.id + "[" + i + "]";
            }
        }
        for (var i = 0; i < this.childNodes.length; i++) {
            bottom = this.childNodes[i].bottom(bottom, this.x + _x, this.y + _y);
        }
        return bottom;
    }
});
